package com.lfz;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.AsyncRabbitTemplate;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.annotation.EnableAsync;

@Configuration
@EnableAsync
public class RabbitConfig {

    /**
     * 同步RPC队列
     */
    public static final String QUEUE_SYNC_RPC = "rpc.sync";

    /**
     * 异步RPC队列，使用临时回复队列，或者使用“Direct reply-to”特性
     */
    public static final String QUEUE_ASYNC_RPC = "rpc.async";

    /**
     * 异步RPC队列，每个客户端使用不同的固定回复队列，需要额外提供correlationId以关联请求和响应
     */
    public static final String QUEUE_ASYNC_RPC_WITH_FIXED_REPLY = "rpc.with.fixed.reply";

    @Bean
    public Queue syncRPCQueue() {
        return new Queue(QUEUE_SYNC_RPC);
    }

    @Bean
    public Queue asyncRPCQueue() {
        return new Queue(QUEUE_ASYNC_RPC);
    }

    @Bean
    public Queue fixedReplyRPCQueue() {
        return new Queue(QUEUE_ASYNC_RPC_WITH_FIXED_REPLY);
    }

    @Bean
    public Queue repliesQueue() {
        return new AnonymousQueue();
    }

    @Bean
    @Primary
    public SimpleMessageListenerContainer replyContainer(ConnectionFactory connectionFactory) {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
        container.setQueueNames(repliesQueue().getName());
        return container;
    }

    @Bean
    public AsyncRabbitTemplate asyncRabbitTemplate(RabbitTemplate template, SimpleMessageListenerContainer container) {
        return new AsyncRabbitTemplate(template, container);
    }



    public static final String EXCHANGE_SYNC_NAME = "spring-boot-direct";
    public static final String DIRECT_QUEUE_NAME = "msgQueue";
    public static final String ROUTING_KEY_MSG_ADD = "msg.add";

    // 消费端和生产端配置：声明路由模式的交换机，由框架维护
    @Bean
    public DirectExchange getExchange(){
        return new DirectExchange(EXCHANGE_SYNC_NAME);
    }

    // 消费端配置：声明一个队列，由框架维护，如果同一交换机有绑定队列，直接使用，没有绑定则创建
    @Bean
    public Queue getQueue(){
        return new Queue(DIRECT_QUEUE_NAME);
    }
    // 消费端配置：将队列绑定到RoutingKey和Exchange，使用bind对象维护队列交换机的绑定
    @Bean
    public Binding binding(){ ;
        return BindingBuilder.bind(getQueue()).to(getExchange()).with(ROUTING_KEY_MSG_ADD);
    }


}
